<?php

const RPC_EOL = "\r\n\r\n";

//新增解决rpc外部调用，被截断\r\n的问题
const RPC_EOL_NEW = "\r\n";

/**
 * @param $host
 * @param $class
 * @param $method
 * @param $param
 * @param string $version
 * @param array $ext
 * @return mixed
 * @throws Exception
 */
function RpcRequest($host, $class, $method, $param, $version = '1.0', $ext = []) {
    $fp = stream_socket_client($host, $errno, $errstr);
    if (!$fp) {
        throw new Exception("stream_socket_client fail errno={$errno} errstr={$errstr}");
    }

    $time_out = config('service.time_out', 3);

    $start_time = time();

    stream_set_blocking($fp, true);
    stream_set_timeout($fp, $time_out);

    $req = [
        "jsonrpc" => '2.0',
        "method" => sprintf("%s::%s::%s", $version, $class, $method),
        'params' => $param,
        'id' => '',
        'ext' => $ext,
    ];
    $data = json_encode($req) . RPC_EOL;
    fwrite($fp, $data);

    $result = '';
    while (!feof($fp)) {
        $tmp = stream_socket_recvfrom($fp, 1024);

        $diff = time() - $start_time;
        $status = stream_get_meta_data($fp);
        if ($diff > $time_out || $status['timed_out']) {
            break;
        }

        if (($pos = strpos($result.$tmp, RPC_EOL)) !== false) {
            $result .= substr($tmp, 0, $pos);
            break;
        } else {
            $result .= $tmp;
        }
    }

    fclose($fp);
    return json_decode($result, true);
}

/**
 * 生成缓存 KEY 值
 * @param $requestData
 * @return string
 */
function getCatchKey($requestData){
    // 删除唯一标识
    if (isset($requestData['trace_id'])) {
        unset($requestData['trace_id']);
    }
    return $requestData['service'] . ':' . md5(json_encode($requestData));
}
